import { type AxiosPromise, type AxiosRequestConfig } from 'axios';
import { setupAxiosConfig } from '@/api/request/my_axios';

import { type ResponseData } from '@/types/interface/base_interface';

const Request = class {
  public readonly url: string;

  public readonly data: ResponseData;

  public readonly config: AxiosRequestConfig;

  public instance = setupAxiosConfig().instance; //axios的实例必须在Request类中调用才能生效，否则会提示无法使用pinia对象

  // url表示加载地址
  // arg表示传递的参数，如果是post、put、patch方式，要以json传递字符，需要先转换为Json字符串再调用本方法。如果直接传递对象参数，将调用相应的param参数
  constructor(url: string, data: any = {}, config?: AxiosRequestConfig) {
    this.url = url;
    this.data = data;
    if (typeof config !== 'undefined') {
      this.config = config;
    } else {
      this.config = {};
    }
  }
  /*  post():AxiosPromise|object {
    return new Promise((resolve, reject) => {
      if (typeof this.data !== 'string') { // 如果data不是字符串类型，说明传递过来的是一个对象.
        instance.post(this.url,null,{
          params: this.data,
        }) .then((res) => { // res表示成功返回的服务端数据
          resolve(res);
        }).catch((error) => { // error 表示服务端响应的http错误状态信息
          reject(error);
        });
        /!*
        //之前使用地址栏拼接，也是可以实现，不过没有必要。保留后期也许某个地方需要
        Object.keys(this.data).forEach((key) => {
          // if (Object.prototype.hasOwnProperty.call(this.data, item)) {
          // param += `${encodeURIComponent(key)}=${encodeURIComponent(this.data[key])}&`;
          this.url += `${this.url.indexOf('?') > 0 ? '&' : '?'}${key}=${this.data[key]}`;
        });
        instance.post(this.url)
          .then((res) => { // res表示成功返回的服务端数据
            resolve(res);
          }).catch((error) => { // error 表示服务端响应的http错误状态信息
            reject(error);
          });*!/
      } else { // 如果data是字符串类型，说明传递过来的是json字符串；
        instance.post(this.url, this.data)
          .then((res) => { // res表示成功返回的服务端数据
            resolve(res);
          }).catch((error) => { // error 表示服务端响应的http错误状态信息
            reject(error);
          });
      }
    });
  } */

  // get(): AxiosPromise<ResponseData> {
  //   return instance.get(this.url, this.config);
  // }

  get(): Promise<ResponseData> {
    //查询的话是表单值通过config传递的。
    //如果原来的查询条件的prams没有值，即避免原来有值（如分页）出问题
    //将表单转换为查询参数，供地址栏拼接。后为了避免地址栏参数过多取消
    // const queryParams = new URLSearchParams(Object.entries(this.data)).toString();
    //注意避免下面的行为：因为可能传递的参数原来config就有值，
    //如果data对象传递了实际参数
    if (typeof this.data !== 'undefined' && this.data != null && Object.keys(this.data).length > 0) {
      //如果原来的config中的params存在值，则要避免覆盖。
      if (typeof this.config.params !== 'undefined' && Object.keys(this.config.params).length > 0) {
        const params = Object.assign(this.config.params, this.data);
        Object.assign(this.config, {
          params
        });
      } else {
        //如果原来的config中的params没有值
        Object.assign(this.config, {
          params: this.data
        });
      }
    }
    return this.instance.get(this.url, this.config);
  }

  // 如果是除了json还有query方式要传递，则在config参数中使用下面的类型传递
  //   {
  //       params: this.data,
  //     }
  post(): Promise<ResponseData> {
    return this.instance.post(this.url, this.data, this.config);
  }

  //备份：所有编辑操作的类型都是这个
  // put(): AxiosPromise | Record<string, unknown> {
  //   return this.instance.put(this.url, this.data, this.config);
  // }

  put(): Promise<ResponseData> {
    return this.instance.put(this.url, this.data, this.config);
  }

  patch(): Promise<ResponseData> {
    return this.instance.patch(this.url, this.data, this.config);
  }

  delete(): Promise<ResponseData> {
    //如果data对象传递了实际参数
    if (typeof this.data !== 'undefined' && this.data != null && Object.keys(this.data).length > 0) {
      //如果原来的config中的params存在值，则要避免覆盖。
      if (typeof this.config.data !== 'undefined' && Object.keys(this.config.data).length > 0) {
        const data = Object.assign(this.config.data, this.data);
        Object.assign(this.config, {
          data
        });
      } else {
        //如果原来的config中的params没有值
        Object.assign(this.config, {
          data: this.data
        });
      }
    }
    return this.instance.delete(this.url, this.config);
  }
};

export default Request;
